package com.tiecode.fixed.namer;

import com.tiecode.platform.compiler.api.process.TaskEvent;
import com.tiecode.platform.compiler.source.tree.MethodTree;
import com.tiecode.platform.compiler.source.tree.Tree;
import com.tiecode.platform.compiler.toolchain.env.CompilationEnv;
import com.tiecode.platform.compiler.toolchain.env.Context;
import com.tiecode.platform.compiler.toolchain.processor.AnnotationProvider;
import com.tiecode.platform.compiler.toolchain.tree.TCTree;
import com.tiecode.platform.compiler.toolchain.tree.TreePrinter;
import com.tiecode.platform.compiler.toolchain.tree.symbol.Symbol;
import com.tiecode.platform.compiler.util.PinYinUtils;

import java.util.List;

import cn.tiecode.api.event.TiecodeCompilerEvent;

public class FixedNamerCompilerEvent implements TiecodeCompilerEvent {
    private Context context;
    private final TreePrinter printer = new TreePrinter();

    @Override
    public void init(Context context) {
        this.context = context;
    }

    @Override
    public void onProvideAnnotation(AnnotationProvider annotationProvider) {

    }

    @Override
    public void onEventStarted(TaskEvent taskEvent) {

    }

    @Override
    public void onEventFinished(TaskEvent taskEvent) {
        if (taskEvent.getKind() != TaskEvent.Kind.ENTER) {
            return;
        }
        CompilationEnv env = context.get(CompilationEnv.key);
        List<TCTree.TCCompilationUnit> units = env.units;
        for (TCTree.TCCompilationUnit unit : units) {
            if (unit.classDefs == null) {
                continue;
            }
            if (unit.pid != null) {
                unit.symbol.outputName = getPackageName(unit.symbol.name);
            }
            for (TCTree.TCClass classDef : unit.classDefs) {
                if (classDef == null) {
                    continue;
                }
                classDef.symbol.outputName = getClassName(classDef.name);
                classDef.symbol.fullOutName = unit.symbol.outputName + "." + classDef.symbol.outputName;
                if (classDef.members == null) {
                    continue;
                }
                modifyMemberNames(classDef);
            }
        }
    }

    private void modifyMemberNames(TCTree.TCClass classDef) {
        for (TCTree.TCAnnotated member : classDef.members) {
            Symbol symbol = member.getSymbol();
            String memberName = getMemberName(member.name);
            if (member.getKind() == Tree.Kind.METHOD) {
                TCTree.TCMethodDeclare tree = (TCTree.TCMethodDeclare) member;
                if (tree.category == MethodTree.Category.EVENT_DECLARE) {
                    symbol.outputName = classDef.symbol.outputName + "_" + memberName;
                } else {
                    symbol.outputName = memberName;
                }
            } else if (member.getKind() == Tree.Kind.EVENT) {
                TCTree.TCEvent tcEvent = (TCTree.TCEvent) member;
                symbol.outputName = printer.getString(tcEvent.target) + "_" + memberName;
            } else {
                symbol.outputName = memberName;
            }
        }
    }

    private String getPackageName(CharSequence name) {
        return PinYinUtils.getPinYin(String.valueOf(name));
    }

    private String getClassName(CharSequence name) {
        return PinYinUtils.getHumpPinYin(String.valueOf(name));
    }

    private String getMemberName(CharSequence name) {
        String text = PinYinUtils.getHumpPinYin(String.valueOf(name));
        return Character.toLowerCase(text.charAt(0)) + text.substring(1);
    }
}
